/*
 * JNISwingWrapper.h  0.4.0 / Nov 17, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#ifndef JNISWINGWRAPPER_H
#define JNISWINGWRAPPER_H

#include "Cute4jCore.h"

// JNISwingWrapper Class. ------------------------------------------------------

/*!
 * \brief JNI Swing Wrapper.
 *
 * \author Slobodan Vrkacevic
 * \version 0.4.0
 */
class CUTE4J_EXPORT JNISwingWrapper
{
public:
  inline static JNIEnv *env();
  inline static bool isSwingThread(JNIEnv *env);
  inline static void checkGUIThread(JNIEnv *env);
public:
  static void checkException();
  static bool testException();
  static void fatalError(const char *errorMessage);
  static void throwInternalError(const char *errorMessage = 0);
  static void throwOutOfMemoryError(const char *errorMessage = 0);
  static void throwRuntimeExcpetion(const char *exceptionMessage = 0);
  static jfieldID getFieldID(jclass cls, const char *name, const char *sig);
  static jfieldID getStaticFieldID(jclass cls, const char *name,
                                   const char *sig);
  static jmethodID getMethodID(jclass cls, const char *name, const char *sig);
  static jmethodID getStaticMethodID(jclass cls, const char *name,
                                     const char *sig);
  static jobject getObjectField(jobject obj, jfieldID fieldID);
  static void setObjectField(jobject obj, jfieldID fieldID, jobject val);
  static jboolean getBooleanField(jobject obj, jfieldID fieldID);
  static void setBooleanField(jobject obj, jfieldID fieldID, jboolean val);
  static jbyte getByteField(jobject obj, jfieldID fieldID);
  static void setByteField(jobject obj, jfieldID fieldID, jbyte val);
  static jchar getCharField(jobject obj, jfieldID fieldID);
  static void setCharField(jobject obj, jfieldID fieldID, jchar val);
  static jshort getShortField(jobject obj, jfieldID fieldID);
  static void setShortField(jobject obj, jfieldID fieldID, jshort val);
  static jint getIntField(jobject obj, jfieldID fieldID);
  static void setIntField(jobject obj, jfieldID fieldID, jint val);
  static jlong getLongField(jobject obj, jfieldID fieldID);
  static void setLongField(jobject obj, jfieldID fieldID, jlong val);
  static jfloat getFloatField(jobject obj, jfieldID fieldID);
  static void setFloatField(jobject obj, jfieldID fieldID, jfloat val);
  static jdouble getDoubleField(jobject obj, jfieldID fieldID);
  static void setDoubleField(jobject obj, jfieldID fieldID, jdouble val);
  static bool callObjectMethod(jobject &result, jobject obj, jmethodID methodID,
                               va_list &args);
  static bool callObjectMethod(jobject &result, jobject obj, jmethodID methodID,
                               ...);
  static bool callBooleanMethod(jboolean &result, jobject obj,
                                jmethodID methodID, va_list &args);
  static bool callBooleanMethod(jboolean &result, jobject obj,
                                jmethodID methodID, ...);
  static bool callByteMethod(jbyte &result, jobject obj, jmethodID methodID,
                             va_list &args);
  static bool callByteMethod(jbyte &result, jobject obj, jmethodID methodID,
                             ...);
  static bool callCharMethod(jchar &result, jobject obj, jmethodID methodID,
                             va_list &args);
  static bool callCharMethod(jchar &result, jobject obj, jmethodID methodID,
                             ...);
  static bool callShortMethod(jshort &result, jobject obj, jmethodID methodID,
                              va_list &args);
  static bool callShortMethod(jshort &result, jobject obj, jmethodID methodID,
                              ...);
  static bool callIntMethod(jint &result, jobject obj, jmethodID methodID,
                            va_list &args);
  static bool callIntMethod(jint &result, jobject obj, jmethodID methodID, ...);
  static bool callLongMethod(jlong &result, jobject obj, jmethodID methodID,
                             va_list &args);
  static bool callLongMethod(jlong &result, jobject obj, jmethodID methodID,
                             ...);
  static bool callFloatMethod(jfloat &result, jobject obj, jmethodID methodID,
                              va_list &args);
  static bool callFloatMethod(jfloat &result, jobject obj, jmethodID methodID,
                              ...);
  static bool callDoubleMethod(jdouble &result, jobject obj, jmethodID methodID,
                               va_list &args);
  static bool callDoubleMethod(jdouble &result, jobject obj, jmethodID methodID,
                               ...);
  static bool callVoidMethod(jobject obj, jmethodID methodID, va_list &args);
  static bool callVoidMethod(jobject obj, jmethodID methodID, ...);
  static jstring toString(jobject obj);
  static jstring newString(const jchar *uchars, jsize len);
  static jstring newStringUTF(const char *bytes);
  static bool callStaticVoidMethod(jclass cls, jmethodID methodID,
                                   va_list &args);
  static bool callStaticVoidMethod(jclass cls, jmethodID methodID, ...);
  static jobject newObject(jclass cls, jmethodID constructor, va_list &args);
  static jobject newObject(jclass cls, jmethodID constructor, ...);
  static jobjectArray newObjectArray(jclass cls, jsize len);
  static jbyteArray newByteArray(jsize len);
  static jobject newGlobalRef(jobject obj);
  static jweak newWeakGlobalRef(jobject obj);
  static void deleteGlobalRef(jobject &objref);
  static void deleteWeakGlobalRef(jweak &wobjref);
  static bool isLiveRef(jweak wobjref);
private:
  friend class SwingDelegate; // uses initialize(JNIEnv *env) and sm_disposed
  static void initialize(JNIEnv *env);
private:
  static JNIEnv *sm_env;
  static bool sm_disposed;
};

// JNISwingWrapper :: Public Static Inline Member Functions. -------------------

/*!
 * \brief Returns JNIEnv pointer.
 *
 * \return env JNIEnv pointer
 */
inline JNIEnv *JNISwingWrapper::env()
{
  return sm_env;
}

/*!
 * \brief Returns \c true if the specified JNIEnv pointer is same as \a sm_env.
 *
 * \param env the JNIEnv pointer
 *
 * \return \c true if JNIEnv pointer \a env is same as \a sm_env
 */
inline bool JNISwingWrapper::isSwingThread(JNIEnv *env)
{
  if (sm_disposed) {
    JNILogger::logError("Swing disposed", "JNISwingWrapper", __LINE__);
    env->FatalError("Swing disposed");  // does not return
  }
  return (sm_env == env);
}

/*!
 * \brief Checks if a GUI object is outside the GUI thread.
 */
inline void JNISwingWrapper::checkGUIThread(JNIEnv *env)
{
  if (sm_disposed) {
    JNILogger::logError("Cute4j Swing disposed", "JNISwingWrapper", __LINE__);
    env->FatalError("Cute4j Swing disposed");  // does not return
  }
  if (sm_env != env) {
    JNISwingWrapper::fatalError("GUI object outside main thread");
  }
}

// Macro Definition. -----------------------------------------------------------

#define SWING_ENV JNISwingWrapper::env()

#endif // JNISWINGWRAPPER_H
